#include "demo_utils.hpp"

#include <atomic>
#include <iostream>
#include <thread>

namespace atomic_examples {
namespace {

/**
 * @brief 使用 std::atomic<bool> 管理服务状态的示例类。
 *
 * 支持 start / stop 调用，并在多线程环境下避免竞态。
 */
class ServiceFlag {
public:
  /**
   * @brief 尝试启动服务。
   *
   * @return 若成功从 false 切换到 true，返回 true；表示服务成功启动。
   *
   * ⚠️ 使用 compare_exchange_strong，保证即便在高争用下也能稳健工作。
   */
  bool start() {
    bool expected = false;
    return running_.compare_exchange_strong(
        expected,
        true,
        std::memory_order_acq_rel);
  }

  /**
   * @brief 查询当前运行状态。
   *
   * @return 服务是否正在运行。
   */
  bool isRunning() const {
    return running_.load(std::memory_order_acquire);
  }

  /**
   * @brief 停止服务。
   *
   * @return 若之前状态为运行中，返回 true；否则返回 false。
   *
   * ✅ 采用 exchange 一次性获取旧值并写入新状态。
   */
  bool stop() {
    return running_.exchange(false, std::memory_order_acq_rel);
  }

private:
  std::atomic<bool> running_{false}; ///< 服务运行状态标志。
};

/**
 * @brief 演示两个线程竞争启动服务，并在最后关闭服务。
 */
void runServiceFlagDemo() {
  printHeader("Atomic Flag Example");

  ServiceFlag flag;

  std::thread t1([&flag]() {
    if (flag.start()) {
      std::cout << "Thread " << std::this_thread::get_id()
                << " started the service\n";
    } else {
      std::cout << "Thread " << std::this_thread::get_id()
                << " found service already running\n";
    }
  });

  std::thread t2([&flag]() {
    if (flag.start()) {
      std::cout << "Thread " << std::this_thread::get_id()
                << " started the service\n";
    } else {
      std::cout << "Thread " << std::this_thread::get_id()
                << " found service already running\n";
    }
  });

  t1.join();
  t2.join();

  std::cout << "Service running? " << std::boolalpha
            << flag.isRunning() << '\n';

  if (flag.stop()) {
    std::cout << "Service stopped successfully\n";
  }
  if (!flag.stop()) {
    std::cout << "Service was already stopped\n";
  }
}

} // namespace
} // namespace atomic_examples

int main() {
  atomic_examples::runServiceFlagDemo();
  return 0;
}